<template>
  <view class="gi-form">
    <sar-form ref="formRef" :model="props.modelValue" scroll-to-first-error>
      <template v-for="item in props.columns">
        <template v-if="item.slotName">
          <slot :name="item.slotName"></slot>
        </template>
        <template v-if="item.type === 'group-title'">
          <sar-alert :key="item.field">{{ item.label }}</sar-alert>
        </template>
        <template v-else>
          <sar-form-item v-if="!isHide(item)" :key="item.field" :label="item.label" :name="item.field" :rules="item.rules">
            <component
              :is="compObj[item.type]"
              :model-value="props.modelValue[item.field]"
              :readonly="isReadonly(item)"
              :disabled="isDisabled(item)"
              v-bind="getComponentProps(item)" @update:model-value="updateModelValue($event, item)"
            ></component>
          </sar-form-item>
        </template>
      </template>
    </sar-form>
  </view>
</template>

<script lang='ts' setup>
import type { FormRules } from 'sard-uniapp'
import type Form from 'sard-uniapp/components/form/form.vue'
import type { ColumnItem, ColumnItemProps, ColumnItemType } from './type'
import GiFormCalendar from '@/components/gi-form-calendar/gi-form-calendar.vue'
import GiFormDatetimePicker from '@/components/gi-form-datetime-picker/gi-form-datetime-picker.vue'
import CheckboxGroup from 'sard-uniapp/components/checkbox-group/checkbox-group.vue'
import CheckboxInput from 'sard-uniapp/components/checkbox-input/checkbox-input.vue'
import Input from 'sard-uniapp/components/input/input.vue'
import PickerInput from 'sard-uniapp/components/picker-input/picker-input.vue'
import PopoutInput from 'sard-uniapp/components/popout-input/popout-input.vue'
import RadioGroup from 'sard-uniapp/components/radio-group/radio-group.vue'
import RadioInput from 'sard-uniapp/components/radio-input/radio-input.vue'
import Rate from 'sard-uniapp/components/rate/rate.vue'
import Slider from 'sard-uniapp/components/slider/slider.vue'
import Stepper from 'sard-uniapp/components/stepper/stepper.vue'
import Switch from 'sard-uniapp/components/switch/switch.vue'
import Upload from 'sard-uniapp/components/upload/upload.vue'

interface Props {
  modelValue: any
  columns: ColumnItem[]
  rules?: FormRules
  readonly?: boolean // 表单只读
}

const props = withDefaults(defineProps<Props>(), {
  columns: () => [],
  fc: () => ({}),
  readonly: false,
})

const emit = defineEmits<{
  (e: 'update:modelValue', value: any): void
}>()

const compObj: Record<string, any> = {
  'input': Input,
  'textarea': Input,
  'picker': PickerInput,
  'stepper': Stepper,
  'datetime-picker': GiFormDatetimePicker,
  'calendar': GiFormCalendar,
  'checkbox-input': CheckboxInput,
  'checkbox-group': CheckboxGroup,
  'radio-input': RadioInput,
  'radio-group': RadioGroup,
  'popout-input': PopoutInput,
  'rate': Rate,
  'slider': Slider,
  'switch': Switch,
  'upload': Upload,
}

const formRef = ref<InstanceType<typeof Form>>()

function updateModelValue(value: any, item: ColumnItem) {
  emit('update:modelValue', Object.assign(props.modelValue, { [item.field]: value }))
}

function getPlaceholder(item: ColumnItem) {
  if (
    ['popout-input'].includes(item.type)
  ) {
    return `请选择${item.label}`
  }
  else if (['textarea'].includes(item.type)) {
    return `请填写${item.label}`
  }
  else {
    return `请输入${item.label}`
  }
}

function getComponentProps(item: ColumnItem) {
  const defaultComponentProps: Record<ColumnItemType, ColumnItemProps> = {
    'input': { clearable: false },
    'textarea': { type: 'textarea', clearable: false, showCount: true, maxlength: 200 },
    'datetime-picker': { type: 'yMdhms' },
    'stepper': { size: 'small', placeholder: '' },
  }
  const obj: any = {
    placeholder: getPlaceholder(item),
    ...defaultComponentProps[item.type],
  }
  return { ...obj, ...item.props }
}

function isHide(item: ColumnItem) {
  if (item.hide === undefined)
    return false
  if (typeof item.hide === 'boolean')
    return item.hide
  if (typeof item.hide === 'function') {
    return item.hide(props.modelValue)
  }
}

function isReadonly(item: ColumnItem) {
  if (props?.readonly === true)
    return true
  if (typeof item?.readonly === 'boolean')
    return item.readonly
  if (typeof item?.readonly === 'function') {
    return item?.readonly(props.modelValue)
  }
  return false
}

function isDisabled(item: ColumnItem) {
  if (item.disabled === undefined)
    return false
  if (typeof item.disabled === 'boolean')
    return item.disabled
  if (typeof item.disabled === 'function') {
    return item.disabled(props.modelValue)
  }
}

watch(
  () => props.modelValue,
  () => {
    console.log('form', toRaw(props.modelValue))
  },
  { immediate: true, deep: true },
)

defineExpose({ formRef })
</script>

<style lang='scss' scoped>

</style>
